package com.yvan.spring.autoconfig;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.nio.charset.Charset;

@Configuration
@ConditionalOnBean(annotation = {EnableCaching.class})
public class RedisCacheAutoConfiguration {
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisCacheAutoConfiguration.class);
    private static final ObjectMapper OM;

    @Value("${spring.cache.expire-time-seconds}")
    public long CacheExpireTimeOfSeconds;

    static {
        OM = new ObjectMapper();
        OM.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        OM.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        LOGGER.warn("invoke cacheManager");
        RedisCacheManager r = new RedisCacheManager(redisTemplate);
        r.setDefaultExpiration(CacheExpireTimeOfSeconds);
        r.setUsePrefix(true);
        return r;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        LOGGER.warn("invoke redisTemplate");
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(OM);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setKeySerializer(new StringRedisSerializer(Charset.forName("UTF-8")));
        template.afterPropertiesSet();
        return template;
    }
}